package com.stm.bi.report;

import com.stm.bi.core.util.DateUtils;
import com.stm.bi.dto.query.RegionalSaleQry;
import com.stm.bi.model.Chart;
import com.stm.bi.model.DateRange;
import com.stm.framework.core.context.UserHolder;
import com.stm.framework.core.util.FileResourceLoader;
import com.stm.framework.core.util.StringUtil;
import com.stm.framework.dbcp.JdbcService;
import com.stm.framework.dto.Response;
import com.stm.saas.api.CalendarCycleRemoteService;
import com.stm.saas.api.ProductConfigRemoteService;
import com.stm.saas.dto.vo.ProductConfigVO;
import com.stm.saas.model.CalendarCycle;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;
import java.math.RoundingMode;

import static com.stm.bi.constant.PlanConstants.TYPE_MONTH;
import static com.stm.bi.constant.IndexConstants.NUMBER_OF_TRANSACTIONS_FIELD;

/**
 * @author liuyx
 * @date 2025/2/18 9:51
 */
@Component
public class RegionalCustomerRankChartQueryExe extends AbsChartQueryExe<RegionalSaleQry, Chart>{
    @Resource
    private JdbcService jdbcService;

    @Resource
    private CalendarCycleRemoteService calendarCycleRemoteService;

    @Resource
    private ProductConfigRemoteService productConfigRemoteService;

    @Override
    public Chart query(Long orgId, String orgNo, RegionalSaleQry query) {
        Chart chart = new Chart();
        List<List<Object>> datas = new ArrayList<>();
        List<String> items = chart.getItems();
        // 查客数
        CalendarCycle cyc = calendarCycleRemoteService.getByOrg().get();
        DateRange dateRange = DateUtils.getYearFirstAndEnd(LocalDate.now().toString(), cyc.getMonth());

        Response<ProductConfigVO> prodResp = productConfigRemoteService.selectByOrgId(UserHolder.getOrgId());
        String salesDefinition = "dealing";
        if(prodResp != null && prodResp.getData() != null) {
            salesDefinition = prodResp.getData().getSalesDefinition();
        }
        if("delivery".equals(salesDefinition)) {
            salesDefinition = "dealing";
        }


        String selectSql = FileResourceLoader.getResourceAsString("/sql/adsBaseProvinceSales.sql");
        List<Map> maps = jdbcService.selectList(selectSql, new Object[]{
                orgId,
                query.getDeptId(),
                TYPE_MONTH,
                salesDefinition,
                dateRange.getStartDate(),
                dateRange.getEndDate(),
                NUMBER_OF_TRANSACTIONS_FIELD});

        if (maps.isEmpty()) {
            return chart;
        }
        // 分组并求添加年度总销量
        Map<String, Map> result = maps.stream()
                .collect(Collectors.groupingBy(
                        m -> (String) m.get("province_name"),
                        Collectors.collectingAndThen(
                                Collectors.toList(),
                                list -> {
                                    // 销量
                                    BigDecimal totalQty = list.stream()
                                            .map(m -> (BigDecimal) m.get(NUMBER_OF_TRANSACTIONS_FIELD))
                                            .filter(Objects::nonNull)
                                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                                    // 新客数
                                    BigDecimal yearNewCustomers = list.stream()
                                            .map(m -> (BigDecimal) m.get("new_customers"))
                                            .filter(Objects::nonNull)
                                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                                    // 老客数
                                    BigDecimal yearOldCustomers = list.stream()
                                            .map(m -> (BigDecimal) m.get("old_customers"))
                                            .filter(Objects::nonNull)
                                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                                    // 新客销售额
                                    BigDecimal yearNewCustomerSales = list.stream()
                                            .map(m -> (BigDecimal) m.get("new_customer_sales"))
                                            .filter(Objects::nonNull)
                                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                                    // 老客销售额
                                    BigDecimal yearOldCustomerSales = list.stream()
                                            .map(m -> (BigDecimal) m.get("old_customer_sales"))
                                            .filter(Objects::nonNull)
                                            .reduce(BigDecimal.ZERO, BigDecimal::add);


                                    // 创建一个新的Map来存储汇总数据
                                    Map<String, Object> aggregatedMap = new HashMap<>();
                                    for (Map map : list) {
                                        aggregatedMap.putAll(map);
                                    }
                                    aggregatedMap.put("yearTotalQty", totalQty);
                                    aggregatedMap.put("yearNewCustomers", yearNewCustomers);
                                    aggregatedMap.put("yearOldCustomers", yearOldCustomers);
                                    aggregatedMap.put("yearNewCustomerSales", yearNewCustomerSales);
                                    aggregatedMap.put("yearOldCustomerSales", yearOldCustomerSales);
                                    return aggregatedMap;
                                }
                        )
                ));

        // 将分组后的结果转换为列表并按 numberOfTransactions 字段倒序排序
        List<Map.Entry<String, Map>> sortedList = new ArrayList<>(result.entrySet());
        sortedList.sort((e1, e2) -> {
            int count1 = ((Number) e1.getValue().get("yearTotalQty")).intValue();
            int count2 = ((Number) e2.getValue().get("yearTotalQty")).intValue();
            return Integer.compare(count2, count1); // 倒序排序
        });
        sortedList.removeIf(e -> e.getKey().equals("-99"));
        // 截取前10个条目
        List<Map.Entry<String, Map>> topFiveEntries = sortedList.stream()
                .limit(10)
                .collect(Collectors.toList());

        // 将截取后的列表转换回 Map
        Map<String, Map> topFiveResult = new LinkedHashMap<>();
        for (Map.Entry<String, Map> entry : topFiveEntries) {
            topFiveResult.put(entry.getKey(), entry.getValue());
        }

        // 查全国
        items.add("新客数");
        items.add("老客数");
        items.add("新客客单");
        items.add("老客客单");
        for (String key : topFiveResult.keySet()) {
            List<Object> data = new ArrayList<>();
            Map map = result.get(key);
            String name  = key;
            if (StringUtil.isNotEmpty(key) && key.equals("-99")){
                name = "其他";
            }
            data.add(key);
            BigDecimal yearNewCustomers = (BigDecimal) map.get("yearNewCustomers");
            BigDecimal yearOldCustomers = (BigDecimal) map.get("yearOldCustomers");
            data.add(yearNewCustomers);
            data.add(yearOldCustomers);
            // 客单 = 销售额 / 客数
            BigDecimal yearNewCustomerSales = (BigDecimal) map.get("yearNewCustomerSales");
            BigDecimal yearOldCustomerSales = (BigDecimal) map.get("yearOldCustomerSales");
            if (yearNewCustomers.compareTo(BigDecimal.ZERO) != 0) {
                data.add(yearNewCustomerSales.divide(yearNewCustomers, 2, RoundingMode.HALF_UP));
            } else {
                data.add(BigDecimal.ZERO);
            }
            if (yearOldCustomers.compareTo(BigDecimal.ZERO) != 0) {
                data.add(yearOldCustomerSales.divide(yearOldCustomers, 2, RoundingMode.HALF_UP));
            } else {
                data.add(BigDecimal.ZERO);
            }
            datas.add(data);
        }
        chart.setItems(items).setDatas(datas);
        return chart;
    }

    @Override
    public String getReportName() {
        return null;
    }
}
